/**
 * 国际化翻译
 * @author huyongkang<huyongkang@yolanda.hk>
 * @version 1.0.0
 * @description
 * 要求的语言包格式为
 * {
 *    'zh_CN': {
 *        'weight': '体重',
 *        deepState: {
 *          foo: '张三',
 *        },
 *     },
 *     'en': {
 *        'weight': 'weight',
 *      },
 *      // ...其他语言
 * }
 * @usage
 * const i18n = new I18n(langPack)
 * // 或者i18n.t
 * i18n.translate('weight')
 * // 支持namespace方式
 * i18n.t('deepState.foo') // 返回张三
 * // 格式化显示，使用{索引}作为占位符
 * i18n.t('i finished work at {0}, {1}', '18:30', '07/27 2020')
 * 
 */
import {
  namespace,
  hasNamespace,
  transferMetaCharacters,
} from './helper';

function defaultFallback(scheme, lang, langPack) {
  return namespace(langPack, `${lang}.${scheme}`);
}

export default class I18n {
  // 当前语言
  lang;

  // 回退语言
  fallbackLang = 'zh_CN';
  // 对应语言字段不存在时的回退函数
  fallback = defaultFallback;

  // 当前语言包
  langPack;

  /**
   * 
   * @param {object} params
   * @param {string} params.langPack
   * @param {string} params.lang
   * @param {Function} params.wrapCtx 对this对象重新处理，一般用于使用类似于Vue.observable的方法使其变成响应式数据
   */
  constructor({ langPack, lang = 'zh_CN', wrapCtx } = {}) {
    this.langPack = langPack;
    this.lang = lang;
    if (typeof wrapCtx === 'function') {
      return wrapCtx(this);
    }
    return this;
  }

  get getLang() {
    return this.lang;
  }
  setLang(lang) {
    this.lang = lang;
  }

  get getLangPack() {
    return this.langPack;
  }
  
  setLangPack(langPack) {
    this.langPack = langPack;
  }

  get getFallbackLang() {
    return this.fallbackLang;
  }

  setFallbackLang(fallbackLang) {
    this.fallbackLang = fallbackLang;
  }

  set setFallback(fallback) {
    this.fallback = fallback;
  }

  translate(scheme, ...params) {
    const exist = hasNamespace(this.langPack, `${this.lang}.${scheme}`);
    let value = exist 
      ? namespace(this.langPack, `${this.lang}.${scheme}`)
      : this.fallback(scheme, this.fallbackLang, this.langPack);
    if (value) {
      const mathRes = value.match(/\{(\d+)\}/g);
      if (mathRes) {
        mathRes.forEach((m) => {
          const idx = m.replace(/\s|\{|\}/g, '');
          value = value.replace(new RegExp(transferMetaCharacters(m), 'g'), params[idx]);
        });
      }
    }
    return value;
  }
  // translate的简写
  t(...args) {
    return this.translate(...args);
  }
}
